<?php
/**
 * 将php dss1签名数据格式，即ans1，转换为dotNET使用的格式，即 r+s
 * @param string $signature  php签名数据
 * @return string dotNET格式的签名数据
 */
function toDotNETDSS1Signation($signature){
  $pos=4;
  $rcount=ord($signature[$pos-1]);

  if($rcount==20){
	$ans1r=substr($signature,$pos,20);
	$pos+=20;
  } 
  else if($rcount>20){ 
	$ans1r=substr($signature,$pos+1,20);
	$pos+=21;
  }
  else{
    $ans1r=substr($signature,$pos,$rcount);
    for($i=0;$i<20-$rcount;$i++) $ans1r = chr(0) . $ans1r;
    $pos+=$rcount; 	
  }  

  $pos+=2;
  $rcount=ord($signature[$pos-1]);

  if($rcount==20)	$ans1s=substr($signature,$pos,20);
  else if($rcount>20)	$ans1s=substr($signature,$pos+1,20);
  else{
  	$ans1s=substr($signature,$pos,$rcount);
  	for($i=0;$i<20-$rcount;$i++) $ans1s = chr(0) . $ans1s;
  }  
  return  $ans1r . $ans1s;	
}
/**
 * 将dotNET使用的格式，即 r+s,转换为php dss1签名数据格式，即ans1。
 * @param string $signature  dotNET格式的签名数据
 * @return string php格式签名数据
 */
function fromDotNETDSS1Signation($signature){
	$ans1r=substr($signature,0,20);
	$ans1s=substr($signature,20,20);
	$head=chr(hexdec('30')).chr(hexdec('2C')); 
	$sep=chr(hexdec('02')).chr(hexdec('14'));
	return $head.$sep.$ans1r.$sep.$ans1s;
}

/**
 * 数据签名
 * @param string $data  需要签名的数据
 * @param string $privkey  私钥
 * @param boolean $keyisfile  私钥是否是文件
 * @param int $method  签名方法，OPENSSL_ALGO_SHA1,OPENSSL_ALGO_DSS1,OPENSSL_ALGO_MD5
 * @param string $pwd  私钥的密码，如果没有设为NULL
 * @return string 签名结果
 */
function data_digest_sign($data,$privkey,$keyisfile=false,$method=OPENSSL_ALGO_SHA1,$pwd=NULL) {
        if($keyisfile){
        	if(file_exists($privkey))
        	  $privkey=file_get_contents($privkey);
        	else
        	  throw new Exception('找不到私钥文件,' . $privkey);
        }
        if(isset($pwd))
          $key=openssl_pkey_get_private($privkey,$pwd);
        else 
          $key=openssl_pkey_get_private($privkey);
        if(! $key)
          throw new Exception('得不到私钥 ,' . openssl_error_string()); 
          
        $result=openssl_sign($data,$sign,$key,$method);
        openssl_free_key($key);
        if(!$result)
          throw new Exception('签名失败 ,' . openssl_error_string());
		return $sign;
}
/**
 * 数据签名验证
 * @param string $data  需要签名验证的数据
 * @param string $sign  签名结果
 * @param string $pubkey  公钥
 * @param boolean $keyisfile  公钥是否是文件
 * @param int $method  签名方法，OPENSSL_ALGO_SHA1,OPENSSL_ALGO_DSS1,OPENSSL_ALGO_MD5
 * @return booelean true:签名验证通过，否则，验证失败。
 */	
 function data_digest_verify($data,$sign,$pubkey,$keyisfile=false,$method=OPENSSL_ALGO_SHA1) {
        if($keyisfile){
        	if(file_exists($pubkey))
        	  $pubkey=file_get_contents($pubkey);
        	else
        	  throw new Exception('找不到公钥文件,' . $pubkey);
        }
        $key=openssl_pkey_get_public($pubkey);
        if(! $key)
          throw new Exception('得不到公钥 ,' . openssl_error_string()); 
        $result=openssl_verify($data,$sign,$key,$method);
        openssl_free_key($key);
        if($result===-1)
          throw new Exception('验证失败 ,' . openssl_error_string());
		return $result>0;
}	

